#include "si24r1_port.h"
#include "si24r1.h"

#define DBG_SECTION_NAME  "si24r1/port"
#define DBG_LEVEL         DBG_LOG
#include <rtdbg.h>

static int si24r1_read_reg(struct hal_si24r1_port* halport, uint8_t reg, uint8_t* buf, uint8_t len)
{
    reg &= SI24R1_CMD_R_REGISTER;
    return rt_spi_send_then_recv(halport->spi, &reg, 1, buf, len);
}
static int si24r1_write_reg(struct hal_si24r1_port* halport, uint8_t reg, uint8_t* buf, uint8_t len)
{
    reg |= SI24R1_CMD_W_REGISTER;
    return rt_spi_send_then_send(halport->spi, &reg, 1, buf, len);
}
static int si24r1_write(struct hal_si24r1_port* halport, uint8_t cmd, uint8_t* buf, uint8_t len)
{
    if(buf == NULL || len == 0)
    {
        return rt_spi_send(halport->spi, &cmd, 1);
    }
    return rt_spi_send_then_send(halport->spi, &cmd, 1, buf, len);
}
static int si24r1_read(struct hal_si24r1_port* halport, uint8_t cmd, uint8_t* buf, uint8_t len)
{
    if(buf == NULL || len == 0)
    {
        return rt_spi_send(halport->spi, &cmd, 1);
    }
    return rt_spi_send_then_recv(halport->spi, &cmd, 1, buf, len);
}
static void si24r1_set_ce(struct hal_si24r1_port* halport)
{

    rt_pin_mode(halport->ce_pin, PIN_MODE_OUTPUT);
    rt_pin_write(halport->ce_pin, PIN_HIGH);
}

static void si24r1_reset_ce(struct hal_si24r1_port* halport)
{
    rt_pin_mode(halport->ce_pin, PIN_MODE_OUTPUT);
    rt_pin_write(halport->ce_pin, PIN_LOW);
}

static int si24r1_read_irq_pin(struct hal_si24r1_port* halport)
{
    rt_pin_mode(halport->irq_pin, PIN_MODE_INPUT);
    return rt_pin_read(halport->irq_pin);
}
const static struct hal_si24r1_port_ops si24ri_port_ops = {
    .read_reg = si24r1_read_reg,
    .write_reg = si24r1_write_reg,
    .write = si24r1_write,
    .read = si24r1_read,
    .set_ce = si24r1_set_ce,
    .reset_ce = si24r1_reset_ce,
    .read_irq_pin = si24r1_read_irq_pin,
};

int hal_si24r1_port_init(
    struct hal_si24r1_port* halport,
    char* spi_dev_name,
    int ce_pin,
    int irq_pin,
    void(*irq_callback)(void* param),
    void* param)
{
    struct rt_spi_device* dev;
    RT_ASSERT(halport != RT_NULL);

    dev = (struct rt_spi_device*)rt_device_find(spi_dev_name);
    if (!dev) {
        LOG_E("Can't find spi device %s\n", spi_dev_name);
        return RT_ERROR;
    }

    halport->spi = dev;
    halport->ce_pin = ce_pin;
    halport->irq_pin = irq_pin;
    halport->_irq_cb = irq_callback;
    halport->ops = &si24ri_port_ops;
    halport->spi->config.data_width = 8;
    halport->spi->config.max_hz = 10 * 1000 * 1000;
    halport->spi->config.mode = RT_SPI_MASTER | RT_SPI_MSB | RT_SPI_MODE_0;
    rt_spi_configure(dev, &halport->spi->config);

    rt_pin_mode(ce_pin, PIN_MODE_OUTPUT);
    halport->ops->reset_ce(halport);

    if (irq_pin != -1 && irq_callback != RT_NULL)
    {
        rt_pin_mode(irq_pin, PIN_MODE_INPUT_PULLUP);
        rt_pin_attach_irq(irq_pin, PIN_IRQ_MODE_FALLING, halport->_irq_cb, param);
        rt_pin_irq_enable(irq_pin, PIN_IRQ_ENABLE);
    }
    uint8_t testConfig=0x0E;
    halport->ops->write_reg(halport, SI24R1_REG_CONFIG, &testConfig, 1);
    halport->ops->read_reg(halport, SI24R1_REG_CONFIG, &testConfig, 1);
    if(testConfig != 0x0E)
    {
        LOG_E("si24r1 config error:%02X\n",testConfig);
    }
    else
    {
        LOG_I("si24r1 config ok\n");
    }
    return RT_EOK;
}